<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;

class LogService
{
    /**
     * 日志级别
     */
    const LEVEL_DEBUG = 'debug';
    const LEVEL_INFO = 'info';
    const LEVEL_WARNING = 'warning';
    const LEVEL_ERROR = 'error';
    const LEVEL_CRITICAL = 'critical';

    /**
     * 日志类型
     */
    const TYPE_USER_ACTION = 'user_action';
    const TYPE_SYSTEM = 'system';
    const TYPE_SECURITY = 'security';
    const TYPE_BUSINESS = 'business';
    const TYPE_ERROR = 'error';
    const TYPE_PERFORMANCE = 'performance';

    /**
     * 记录用户操作日志
     */
    public function logUserAction(string $action, array $data = [], string $level = self::LEVEL_INFO): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_USER_ACTION,
            'action' => $action,
            'user_id' => Auth::id(),
            'data' => $data,
        ]);

        $this->writeLog($level, "User action: {$action}", $context);
    }

    /**
     * 记录系统日志
     */
    public function logSystem(string $message, array $data = [], string $level = self::LEVEL_INFO): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_SYSTEM,
            'data' => $data,
        ]);

        $this->writeLog($level, $message, $context);
    }

    /**
     * 记录安全日志
     */
    public function logSecurity(string $event, array $data = [], string $level = self::LEVEL_WARNING): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_SECURITY,
            'event' => $event,
            'user_id' => Auth::id(),
            'ip' => request()->ip(),
            'user_agent' => request()->userAgent(),
            'data' => $data,
        ]);

        $this->writeLog($level, "Security event: {$event}", $context);
    }

    /**
     * 记录业务日志
     */
    public function logBusiness(string $operation, array $data = [], string $level = self::LEVEL_INFO): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_BUSINESS,
            'operation' => $operation,
            'user_id' => Auth::id(),
            'data' => $data,
        ]);

        $this->writeLog($level, "Business operation: {$operation}", $context);
    }

    /**
     * 记录错误日志
     */
    public function logError(\Throwable $exception, array $data = []): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_ERROR,
            'exception' => get_class($exception),
            'message' => $exception->getMessage(),
            'file' => $exception->getFile(),
            'line' => $exception->getLine(),
            'trace' => $exception->getTraceAsString(),
            'user_id' => Auth::id(),
            'data' => $data,
        ]);

        $this->writeLog(self::LEVEL_ERROR, "Exception: {$exception->getMessage()}", $context);
    }

    /**
     * 记录性能日志
     */
    public function logPerformance(string $operation, float $duration, array $data = []): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_PERFORMANCE,
            'operation' => $operation,
            'duration' => $duration,
            'user_id' => Auth::id(),
            'data' => $data,
        ]);

        $level = $duration > 5.0 ? self::LEVEL_WARNING : self::LEVEL_INFO;
        $this->writeLog($level, "Performance: {$operation} took {$duration}s", $context);
    }

    /**
     * 记录API请求日志
     */
    public function logApiRequest(Request $request, $response = null, float $duration = null): void
    {
        $context = $this->buildContext([
            'type' => 'api_request',
            'method' => $request->method(),
            'url' => $request->fullUrl(),
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent(),
            'user_id' => Auth::id(),
            'request_data' => $this->sanitizeRequestData($request->all()),
            'response_status' => $response ? $response->getStatusCode() : null,
            'duration' => $duration,
        ]);

        $level = $response && $response->getStatusCode() >= 400 ? self::LEVEL_WARNING : self::LEVEL_INFO;
        $this->writeLog($level, "API Request: {$request->method()} {$request->path()}", $context);
    }

    /**
     * 记录数据库查询日志
     */
    public function logDatabaseQuery(string $query, array $bindings = [], float $duration = null): void
    {
        $context = $this->buildContext([
            'type' => 'database_query',
            'query' => $query,
            'bindings' => $bindings,
            'duration' => $duration,
            'user_id' => Auth::id(),
        ]);

        $level = $duration && $duration > 1.0 ? self::LEVEL_WARNING : self::LEVEL_DEBUG;
        $this->writeLog($level, "Database Query", $context);
    }

    /**
     * 记录缓存操作日志
     */
    public function logCacheOperation(string $operation, string $key, $value = null, bool $success = true): void
    {
        $context = $this->buildContext([
            'type' => 'cache_operation',
            'operation' => $operation,
            'key' => $key,
            'value' => $this->sanitizeValue($value),
            'success' => $success,
            'user_id' => Auth::id(),
        ]);

        $level = $success ? self::LEVEL_DEBUG : self::LEVEL_WARNING;
        $this->writeLog($level, "Cache {$operation}: {$key}", $context);
    }

    /**
     * 记录邮件发送日志
     */
    public function logEmail(string $to, string $subject, bool $success = true, string $error = null): void
    {
        $context = $this->buildContext([
            'type' => 'email',
            'to' => $to,
            'subject' => $subject,
            'success' => $success,
            'error' => $error,
            'user_id' => Auth::id(),
        ]);

        $level = $success ? self::LEVEL_INFO : self::LEVEL_ERROR;
        $this->writeLog($level, "Email sent to: {$to}", $context);
    }

    /**
     * 记录支付日志
     */
    public function logPayment(string $operation, array $data = [], bool $success = true): void
    {
        $context = $this->buildContext([
            'type' => 'payment',
            'operation' => $operation,
            'success' => $success,
            'user_id' => Auth::id(),
            'data' => $this->sanitizePaymentData($data),
        ]);

        $level = $success ? self::LEVEL_INFO : self::LEVEL_ERROR;
        $this->writeLog($level, "Payment {$operation}", $context);
    }

    /**
     * 记录订单日志
     */
    public function logOrder(string $action, $order, array $data = []): void
    {
        $context = $this->buildContext([
            'type' => 'order',
            'action' => $action,
            'order_id' => is_object($order) ? $order->id : $order,
            'order_number' => is_object($order) ? $order->order_number : null,
            'user_id' => Auth::id(),
            'data' => $data,
        ]);

        $this->writeLog(self::LEVEL_INFO, "Order {$action}", $context);
    }

    /**
     * 记录商品日志
     */
    public function logProduct(string $action, $product, array $data = []): void
    {
        $context = $this->buildContext([
            'type' => 'product',
            'action' => $action,
            'product_id' => is_object($product) ? $product->id : $product,
            'product_name' => is_object($product) ? $product->name : null,
            'user_id' => Auth::id(),
            'data' => $data,
        ]);

        $this->writeLog(self::LEVEL_INFO, "Product {$action}", $context);
    }

    /**
     * 记录售后日志
     */
    public function logAfterSales(string $action, $afterSales, array $data = []): void
    {
        $context = $this->buildContext([
            'type' => 'after_sales',
            'action' => $action,
            'after_sales_id' => is_object($afterSales) ? $afterSales->id : $afterSales,
            'user_id' => Auth::id(),
            'data' => $data,
        ]);

        $this->writeLog(self::LEVEL_INFO, "After-sales {$action}", $context);
    }

    /**
     * 记录登录日志
     */
    public function logLogin(string $email, bool $success = true, string $error = null): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_SECURITY,
            'event' => 'login',
            'email' => $email,
            'success' => $success,
            'error' => $error,
            'ip' => request()->ip(),
            'user_agent' => request()->userAgent(),
        ]);

        $level = $success ? self::LEVEL_INFO : self::LEVEL_WARNING;
        $this->writeLog($level, "Login attempt: {$email}", $context);
    }

    /**
     * 记录登出日志
     */
    public function logLogout(int $userId): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_SECURITY,
            'event' => 'logout',
            'user_id' => $userId,
            'ip' => request()->ip(),
        ]);

        $this->writeLog(self::LEVEL_INFO, "User logout", $context);
    }

    /**
     * 记录权限拒绝日志
     */
    public function logPermissionDenied(string $permission, string $resource = null): void
    {
        $context = $this->buildContext([
            'type' => self::TYPE_SECURITY,
            'event' => 'permission_denied',
            'permission' => $permission,
            'resource' => $resource,
            'user_id' => Auth::id(),
            'ip' => request()->ip(),
        ]);

        $this->writeLog(self::LEVEL_WARNING, "Permission denied: {$permission}", $context);
    }

    /**
     * 记录文件操作日志
     */
    public function logFileOperation(string $operation, string $path, bool $success = true, string $error = null): void
    {
        $context = $this->buildContext([
            'type' => 'file_operation',
            'operation' => $operation,
            'path' => $path,
            'success' => $success,
            'error' => $error,
            'user_id' => Auth::id(),
        ]);

        $level = $success ? self::LEVEL_INFO : self::LEVEL_ERROR;
        $this->writeLog($level, "File {$operation}: {$path}", $context);
    }

    /**
     * 构建日志上下文
     */
    private function buildContext(array $data): array
    {
        return array_merge([
            'timestamp' => now()->toISOString(),
            'request_id' => request()->header('X-Request-ID'),
        ], $data);
    }

    /**
     * 写入日志
     */
    private function writeLog(string $level, string $message, array $context): void
    {
        Log::channel('single')->{$level}($message, $context);
    }

    /**
     * 清理请求数据（移除敏感信息）
     */
    private function sanitizeRequestData(array $data): array
    {
        $sensitiveKeys = ['password', 'password_confirmation', 'token', 'secret', 'key'];
        
        foreach ($sensitiveKeys as $key) {
            if (isset($data[$key])) {
                $data[$key] = '***';
            }
        }
        
        return $data;
    }

    /**
     * 清理支付数据（移除敏感信息）
     */
    private function sanitizePaymentData(array $data): array
    {
        $sensitiveKeys = ['card_number', 'cvv', 'expiry', 'pin'];
        
        foreach ($sensitiveKeys as $key) {
            if (isset($data[$key])) {
                $data[$key] = '***';
            }
        }
        
        return $data;
    }

    /**
     * 清理值（限制长度）
     */
    private function sanitizeValue($value): mixed
    {
        if (is_string($value) && strlen($value) > 1000) {
            return substr($value, 0, 1000) . '...';
        }
        
        return $value;
    }

    /**
     * 获取日志统计
     */
    public function getLogStats(int $days = 7): array
    {
        $logFile = storage_path('logs/laravel.log');
        
        if (!file_exists($logFile)) {
            return [
                'total_logs' => 0,
                'error_logs' => 0,
                'warning_logs' => 0,
                'info_logs' => 0,
                'by_type' => [],
            ];
        }
        
        $lines = file($logFile, FILE_IGNORE_NEW_LINES);
        $cutoffDate = now()->subDays($days);
        $stats = [
            'total_logs' => 0,
            'error_logs' => 0,
            'warning_logs' => 0,
            'info_logs' => 0,
            'by_type' => [],
        ];
        
        foreach ($lines as $line) {
            if (preg_match('/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]/', $line, $matches)) {
                $logDate = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $matches[1]);
                
                if ($logDate->lt($cutoffDate)) {
                    continue;
                }
                
                $stats['total_logs']++;
                
                if (strpos($line, '.ERROR:') !== false) {
                    $stats['error_logs']++;
                } elseif (strpos($line, '.WARNING:') !== false) {
                    $stats['warning_logs']++;
                } elseif (strpos($line, '.INFO:') !== false) {
                    $stats['info_logs']++;
                }
                
                // 按类型统计
                if (preg_match('/"type":"([^"]+)"/', $line, $typeMatches)) {
                    $type = $typeMatches[1];
                    $stats['by_type'][$type] = ($stats['by_type'][$type] ?? 0) + 1;
                }
            }
        }
        
        return $stats;
    }

    /**
     * 清理旧日志
     */
    public function cleanupOldLogs(int $days = 30): int
    {
        $logFile = storage_path('logs/laravel.log');
        
        if (!file_exists($logFile)) {
            return 0;
        }
        
        $lines = file($logFile, FILE_IGNORE_NEW_LINES);
        $cutoffDate = now()->subDays($days);
        $newLines = [];
        $removedCount = 0;
        
        foreach ($lines as $line) {
            if (preg_match('/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]/', $line, $matches)) {
                $logDate = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $matches[1]);
                
                if ($logDate->gte($cutoffDate)) {
                    $newLines[] = $line;
                } else {
                    $removedCount++;
                }
            } else {
                $newLines[] = $line;
            }
        }
        
        if ($removedCount > 0) {
            file_put_contents($logFile, implode("\n", $newLines) . "\n");
        }
        
        return $removedCount;
    }
}
